/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cw.controller;

import cw.controller.exceptions.NonexistentEntityException;
import cw.controller.exceptions.PreexistingEntityException;
import cw.entity.GameResult;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import cw.entity.Puzzle;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author VinhTC
 */
public class GameResultJpaController {

    public GameResultJpaController() {
        emf = Persistence.createEntityManagerFactory("CrossWordsAdminPU");
    }
    private EntityManagerFactory emf = null;

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    public void create(GameResult gameResult) throws PreexistingEntityException, Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Puzzle puzzle = gameResult.getPuzzle();
            if (puzzle != null) {
                puzzle = em.getReference(puzzle.getClass(), puzzle.getPuzzleId());
                gameResult.setPuzzle(puzzle);
            }
            em.persist(gameResult);
            if (puzzle != null) {
                puzzle.getGameResultList().add(gameResult);
                puzzle = em.merge(puzzle);
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            if (findGameResult(gameResult.getUserId()) != null) {
                throw new PreexistingEntityException("GameResult " + gameResult + " already exists.", ex);
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void edit(GameResult gameResult) throws NonexistentEntityException, Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            GameResult persistentGameResult = em.find(GameResult.class, gameResult.getUserId());
            Puzzle puzzleOld = persistentGameResult.getPuzzle();
            Puzzle puzzleNew = gameResult.getPuzzle();
            if (puzzleNew != null) {
                puzzleNew = em.getReference(puzzleNew.getClass(), puzzleNew.getPuzzleId());
                gameResult.setPuzzle(puzzleNew);
            }
            gameResult = em.merge(gameResult);
            if (puzzleOld != null && !puzzleOld.equals(puzzleNew)) {
                puzzleOld.getGameResultList().remove(gameResult);
                puzzleOld = em.merge(puzzleOld);
            }
            if (puzzleNew != null && !puzzleNew.equals(puzzleOld)) {
                puzzleNew.getGameResultList().add(gameResult);
                puzzleNew = em.merge(puzzleNew);
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                Integer id = gameResult.getUserId();
                if (findGameResult(id) == null) {
                    throw new NonexistentEntityException("The gameResult with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void destroy(Integer id) throws NonexistentEntityException {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            GameResult gameResult;
            try {
                gameResult = em.getReference(GameResult.class, id);
                gameResult.getUserId();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The gameResult with id " + id + " no longer exists.", enfe);
            }
            Puzzle puzzle = gameResult.getPuzzle();
            if (puzzle != null) {
                puzzle.getGameResultList().remove(gameResult);
                puzzle = em.merge(puzzle);
            }
            em.remove(gameResult);
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public List<GameResult> findGameResultEntities() {
        return findGameResultEntities(true, -1, -1);
    }

    public List<GameResult> findGameResultEntities(int maxResults, int firstResult) {
        return findGameResultEntities(false, maxResults, firstResult);
    }

    private List<GameResult> findGameResultEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            cq.select(cq.from(GameResult.class));
            Query q = em.createQuery(cq);
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    public GameResult findGameResult(Integer id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(GameResult.class, id);
        } finally {
            em.close();
        }
    }

    public int getGameResultCount() {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            Root<GameResult> rt = cq.from(GameResult.class);
            cq.select(em.getCriteriaBuilder().count(rt));
            Query q = em.createQuery(cq);
            return ((Long) q.getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }

    /**
     * method use to get hight scores
     * @param sizeId
     * @return- list object GameResult
     */
    public List<GameResult> getHightScores(int sizeId) {

        List<GameResult> lstResult = new ArrayList<GameResult>();
        try {
            Query query = getEntityManager().createNativeQuery("Select * from tblGameResult r,tblPuzzle p WHERE r.PuzzleId = p.PuzzleId AND p.SizeId =SizeId Order By r.Score DESC", GameResult.class);
            query.setParameter("SizeId", sizeId);
            lstResult = query.getResultList();
            return lstResult;
        } catch (Exception e) {
            Logger.getLogger(GameResultJpaController.class.getName()).log(java.util.logging.Level.SEVERE, null, e);
            return null;
        }
    }

    /**
     * addGameResult
     * @param result
     * @return int
     */
    public int addGameResult(GameResult result) {
        try {
            String sql = "INSERT INTO tblGameResult(UserName,PuzzleId,Score,SpentTime) VALUES(?,?,?,?)";
            Query query = getEntityManager().createNativeQuery(sql);
            query.setParameter(1, result.getUserName());
            query.setParameter(2, result.getPuzzle().getPuzzleId());
            query.setParameter(3, result.getScore());
            query.setParameter(4, result.getSpentTime());

            return query.executeUpdate();
        } catch (Exception e) {
            Logger.getLogger(GameResultJpaController.class.getName()).log(Level.SEVERE, null, e);
            return -1;
        }
    }
}
